package world0;

import java.util.ArrayList;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Polygon;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;

public class CollisionDetection 
{
	private Image image;
	
	/* Point buttom left */
	private float x;
	private float y;
	
	/* Point top right */
	private float x2;
	private float y2;
	
	private Polygon collisionShape;
	//private Polygon collisionPolygon;
	private int mobIndex;
	
	/* State 4 - GenericChar. Shapes - 6 */
	private Polygon collisionAreaMain;
	
	private Polygon collisionAreaButtom;
	private Polygon collisionAreaLeft;
	private Polygon collisionAreaRight;
	private Polygon collisionAreaTop;
	private Polygon collisionAreaSlope;
	private Polygon collisionAreaDebug;
	
	/* Lists */
	ArrayList<LevelObject> solidList;
	
	private int upDown;
	
	boolean collision = false;
	
	public CollisionDetection(float x, float y, Image image, int state) {
		this.x = x;
		this.y = y;
		this.image = image;

		if(state == 1) {
			x2 = (this.image.getWidth());
			y2 = (this.image.getHeight());
			createRectangle();
		}
		
		if(state == 2) {
			x2 = (this.image.getWidth());
			y2 = 5;
			createRectangle();
		}
		
		if(state == 3) {
			x2 = (this.image.getWidth());
			y2 = (this.image.getHeight());
			createTriangleUp();
		}
		
		if(state == 4) { 
			x2 = (this.image.getWidth());
			y2 = (this.image.getHeight());
			createGenericChar();
		}
	}
	
	public CollisionDetection(float x, float y, Image image, int state, int upDown) {
		this.x = x;
		this.y = y;
		this.image = image;

		x2 = (this.image.getWidth());
		y2 = (this.image.getHeight());
		
		if(upDown == 1) {
			createTriangleUp();
		} else if(upDown == 2) {
			createTriangleDown();
		}
	}

	private void createGenericChar() { //Generic Char - 4 HitBoxes
				
		// A -- B
		// |    |
		// D -- C

		collisionAreaMain = new Polygon();
		collisionAreaMain.addPoint(0, 0);   // A
		collisionAreaMain.addPoint(x2, 0);  // B
		collisionAreaMain.addPoint(x2, y2); // C
		collisionAreaMain.addPoint(0, y2);   // D
		collisionAreaMain.setLocation(x, y);
		
		collisionAreaDebug = new Polygon();
		collisionAreaDebug.addPoint(0, 0);   // A
		collisionAreaDebug.addPoint(x2 - 2, 0);  // B
		collisionAreaDebug.addPoint(x2 - 2, y2 - 2); // C
		collisionAreaDebug.addPoint(0, y2 - 2);   // D
		collisionAreaDebug.setLocation(x, y);
		
		collisionAreaTop = new Polygon();
		collisionAreaTop.addPoint(0, 0);   // A
		collisionAreaTop.addPoint(x2 - 4, 0);  // B
		collisionAreaTop.addPoint(x2 - 4, 4); // C
		collisionAreaTop.addPoint(0, 4);   // D
		collisionAreaTop.setLocation(x, y);
		
		collisionAreaButtom = new Polygon();
		collisionAreaButtom.addPoint(0, 0);   // A
		collisionAreaButtom.addPoint(x2 - 4, 0);  // B
		collisionAreaButtom.addPoint(x2 - 4, 4); // C
		collisionAreaButtom.addPoint(0, 4);   // D
		collisionAreaButtom.setLocation(x, y);
		
		collisionAreaLeft = new Polygon();
		collisionAreaLeft.addPoint(0, 0);   // A
		collisionAreaLeft.addPoint(4, 0);  // B
		collisionAreaLeft.addPoint(4, y2 - 4); // C
		collisionAreaLeft.addPoint(0, y2 - 4);   // D
		collisionAreaLeft.setLocation(x, y);
		
		collisionAreaRight = new Polygon();
		collisionAreaRight.addPoint(0, 0);   // A
		collisionAreaRight.addPoint(4, 0);  // B
		collisionAreaRight.addPoint(4, y2 - 4); // C
		collisionAreaRight.addPoint(0, y2 - 4);   // D
		collisionAreaRight.setLocation(x, y);
		
		collisionAreaSlope = new Polygon();
		collisionAreaSlope.addPoint(0, 0);   // A
		collisionAreaSlope.addPoint(4, 0);  // B
		collisionAreaSlope.addPoint(4, 4); // C
		collisionAreaSlope.addPoint(0, 4);   // D
		collisionAreaSlope.setLocation(x, y);
	}
	
	public void createRectangle() {
		collisionShape = new Polygon();
		collisionShape.addPoint(0, 0);
		collisionShape.addPoint(x2, 0);
		collisionShape.addPoint(x2, y2);
		collisionShape.addPoint(0, y2);
		collisionShape.setLocation(x, y);
	}
	
	public void createTriangleUp() {
		collisionShape = new Polygon();
		collisionShape.addPoint(0, 0);
		collisionShape.addPoint(x2, 0);
		collisionShape.addPoint(x2, -y2);
		collisionShape.setLocation(x, y + image.getHeight());
	}
	
	public void createTriangleDown() {
		collisionShape = new Polygon();
		collisionShape.addPoint(0, 0);
		collisionShape.addPoint(x2, 0);
		collisionShape.addPoint(0, -y2);
		collisionShape.setLocation(x, y + image.getHeight());
	}

	public boolean checkCollision(Shape shape) {
		return collisionShape.intersects(shape);
	}
	
	public boolean checkCollision(Shape shape, Shape shape2) {
		return shape.intersects(shape2);
	}
	
	public void update(float x, float y) {
		collisionAreaMain.setCenterX(x);
		collisionAreaMain.setCenterY(y);
		
		collisionAreaDebug.setCenterX(x);
		collisionAreaDebug.setCenterY(y);
		
		collisionAreaTop.setCenterX(x);
		collisionAreaTop.setCenterY(y - y2 / 2);
		
		collisionAreaButtom.setCenterX(x);
		collisionAreaButtom.setCenterY(y - 2 + y2 / 2);
		
		collisionAreaLeft.setCenterX(x - x2 / 2);
		collisionAreaLeft.setCenterY(y);
		
		collisionAreaRight.setCenterX(x + x2 / 2);
		collisionAreaRight.setCenterY(y);

		collisionAreaSlope.setCenterX(x);
		collisionAreaSlope.setCenterY(y - 2 + y2 / 2);
	}
	
	public boolean checkSlope(Shape collisionArea, ArrayList<LevelObject> slopeList) {
		boolean slope = false;
		Shape area;
		
		for (int i = 0; i < slopeList.size(); i++) {
			area = slopeList.get(i).getShape();
		
			if(collisionArea.intersects(area)) {					
				slope = true;
			}
		}
		return slope;
	}
	
	public Shape getShapeArea() {
		return collisionShape;
	}
	
	/* New Check Collisions Methodes */
	
	public boolean mainCheckCollisionLevelObject(ArrayList<LevelObject> solidList) {
		boolean collision = false;
		this.solidList =  solidList;
		
		collision = checkCollisionNEW(collisionAreaMain);
		
		return collision;
	}
	
	public boolean debugCheckCollisionLevelObject(ArrayList<LevelObject> solidList) {
		boolean collision = false;
		this.solidList =  solidList;
		
		collision = checkCollisionNEW(collisionAreaDebug);
		
		return collision;
	}
	
	
	public boolean sideCheckCollisionLevelObject(ArrayList<LevelObject> solidList, String side) {
		boolean collision = false;
		this.solidList = solidList;
		
		if(side.equals("Top")) {
			collision = checkCollisionNEW(collisionAreaTop);
		} else if(side.equals("Buttom")) {
			collision = checkCollisionNEW(collisionAreaButtom);
			if(!collision) {
				collision = checkCollisionCloudeNEW(collisionAreaButtom);
			}
		} else if(side.equals("Left")) {
			collision = checkCollisionNEW(collisionAreaLeft);
		} else if(side.equals("Right")) {
			collision = checkCollisionNEW(collisionAreaRight);
		} else if(side.equals("Debug")) {
			collision = checkCollisionNEW(collisionAreaDebug);
		}
		
		return collision;
	}
	
	public boolean checkCollisionSlope(ArrayList<LevelObject> slopeList) {
		boolean collision = false;
		Shape area;
		
		for (int i = 0; i < slopeList.size(); i++) {
			area = slopeList.get(i).getShape();
		
			if(collisionAreaSlope.intersects(area)) {					
				collision = true;
			}
		}
		return collision;
	}
	
	public boolean mainCheckCollisionSlope(ArrayList<LevelObject> slopeList) {
		boolean collision = false;
		Shape area;
		
		for (int i = 0; i < slopeList.size(); i++) {
			area = slopeList.get(i).getShape();
		
			if(collisionAreaMain.intersects(area)) {					
				collision = true;
			}
		}
		return collision;
	}
	
	public boolean checkCollisionMob(ArrayList<Mob> mobList, int index) {
		boolean collision = false;
		Shape area;
		
		for(int i = 0; i < mobList.size(); i++) {
			area = mobList.get(i).collision.getCollisionArea();
			
			if(collisionAreaMain.intersects(area)) {
				collision = true;
			}
		}
		return collision;
	}
	
	/* Intern CheckCollision */
	private boolean checkCollisionNEW(Shape polygon) {
		boolean collision = false;
		
		for (int i = 0; i < solidList.size(); i++) {
			Shape area;
			area = solidList.get(i).getShape();
			if(polygon.intersects(area) && solidList.get(i).getState() != 2) {
				collision = true;
			}
		}
		return collision;
	}
	
	/* Intern CheckCollisionCloude */
	private boolean checkCollisionCloudeNEW(Shape polygon) {
		boolean collision = false;
		
		for (int i = 0; i < solidList.size(); i++) {
			Shape area;
			area = solidList.get(i).getShape();
			if(polygon.intersects(area) && solidList.get(i).state == 2) {
				collision = true;
			}
		}
		return collision;
	}
	
	public void debugDraw(Graphics g) {
		g.setColor(Color.orange);
		//g.fill(collisionArea);
		
		g.setColor(Color.red);
		g.fill(collisionAreaButtom);
		g.fill(collisionAreaTop);
		g.setColor(Color.blue);
		g.fill(collisionAreaLeft);
		g.fill(collisionAreaRight);
		g.setColor(Color.yellow);
		g.fill(collisionAreaSlope);
	}
	/*******************************************************/
	
	public boolean checkCollisonLevelObject(Shape collisionArea, ArrayList<LevelObject> solidList) {
		collision = false;
		
		for (int i = 0; i < solidList.size(); i++) {
			Shape area;
			area = solidList.get(i).getShape();
			if(collisionArea.intersects(area)) {
				collision = true;
			}
		}
		return collision;
	}
	
	public boolean checkCollisonLevelObjectNonCloud(Shape collisionArea, ArrayList<LevelObject> solidList) {
		collision = false;
		
		for (int i = 0; i < solidList.size(); i++) {
			if(solidList.get(i).getState() != 2) {
				Shape area;
				area = solidList.get(i).getShape();
				if(collisionArea.intersects(area)) {
					collision = true;
				}
			}
		}
		return collision;
	}
	
	public boolean checkCollisionMob(Shape collisionArea, ArrayList<Mob> mobList) {
		collision = false;
		Shape area;
		
		for(int i = 0; i < mobList.size(); i++) {
			area = mobList.get(i).getShape();
			
			if(collisionArea.intersects(area)) {
				collision = true;
			}
		}
		return collision;
	}
	
	/*
	public boolean checkCollisionMobDmg(Shape collisionArea, ArrayList<Mob> mobList) {
		collision = false;
		Shape area;
		
		for(int i = 0; i < mobList.size(); i++) {
			area = mobList.get(i).getShapeTop();
			
			if(collisionArea.intersects(area)) {
				mobIndex = i;
				collision = true;
			}
		}
		return collision;
	}
	*/
	public boolean checkCollisonLevelObject(Shape collisionArea, ArrayList<LevelObject> solidList, int state) {
		collision = false;

		for (int i = 0; i < solidList.size(); i++) {
			Shape area;
			
			if ((solidList.get(i).getState() == 1)) {
				area = solidList.get(i).getShape();
				
				if(collisionArea.intersects(area)) {
				collision = true;
				}
			}
			
			if ((solidList.get(i).getState() == 3)) {
				area = solidList.get(i).getShape();
				
				if(collisionArea.intersects(area)) {
				collision = true;
				}
			}
		}
		return collision;
	}


public boolean checkCollisonLevelObject(Shape collisionArea, ArrayList<LevelObject> solidList, int state, int das) {
		collision = false;

		for (int i = 0; i < solidList.size(); i++) {
			Shape area;
			if ((solidList.get(i).getState() == state)) {
				
				if(state == 1) {
					area = solidList.get(i).getShape();
					if(collisionArea.intersects(area)) {
						collision = true;
					}
				}
				
				if(state == 2) {
					area = solidList.get(i).getShape();
					if(collisionArea.intersects(area)) {
						collision = true;
					}
				}
				
				if(state == 3) {
					area = solidList.get(i).getShape();
					if(collisionArea.intersects(area)) {
						collision = true;
					}
				}
			}
		}
		return collision;
	}

	public int getMobIndex() {
		return mobIndex;
	}
	public Shape getCollisionAreaButtom() {
		return collisionAreaButtom;
	}

	public Shape getCollisionAreaLeft() {
		return collisionAreaLeft;
	}

	public Shape getCollisionAreaRight() {
		return collisionAreaRight;
	}

	public Shape getCollisionAreaTop() {
		return collisionAreaTop;
	}

	public Shape getCollisionAreaSlope() {
		return collisionAreaSlope;
	}

	public Shape getCollisionArea() {
		return collisionAreaDebug;
	}
}
